home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / environment.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  19KB  |  729 lines

  1. /*
  2.  * @(#)environment.c    1.7  4/20/88
  3.  */
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <sys/file.h>
  7. #include "assert.h"
  8. #include "scan.h"
  9. #include "nodes.h"
  10. #include "error.h"
  11. #include "opNames.h"
  12. #include "flags.h"
  13. #include "system.h"
  14. #include <errno.h>
  15. #include "sequence.h"
  16. #include "semantics.h"
  17. #include "map.h"
  18. #include "builtins.h"
  19. #include "environment.h"
  20. #include "trace.h"
  21.  
  22. void resolveGlobal();
  23. extern NodePtr findObjectOperation();
  24. extern void myLink();
  25. #undef NULL
  26. #include "ndbm.h"
  27. #undef NULL
  28. #define NULL 0
  29.  
  30. extern char *emDirectory;
  31. extern char *emdbDirectory;
  32. extern DBM *emDBM;
  33.  
  34. typedef struct sEnvironRecord {
  35.   OID             id;
  36.   struct sEnvironRecord    *next;
  37. } EnvironRecord, *EnvironRecordPtr;
  38. static EnvironRecordPtr writeHead = NULL;
  39. static EnvironRecordPtr readHead  = NULL;
  40. Map environmentMap = NULL;
  41. Map objectTable;
  42.  
  43. Map translateOIDMap = NULL;
  44.  
  45. extern NodePtr loadObject(), readTree();
  46. extern void storeObject(), writeTree();
  47. char *makeOIDFileName(), *makeOIDDotoFileName();
  48.  
  49. void initializeEnvironment()
  50. {
  51.   objectTable = Map_Create();
  52.   environmentMap = Map_Create();
  53.   if (bflag) translateOIDMap = Map_Create();
  54. }
  55.  
  56. void scheduleOutput(id)
  57. OID id;
  58. {
  59.   EnvironmentStage stage;
  60.   EnvironRecordPtr p;
  61.  
  62.   stage = (EnvironmentStage) Map_Lookup(environmentMap, (int)id);
  63.   if (stage == E_Imported) return;
  64.   else if (stage == E_Exported) return;
  65.   else if (stage == E_ScheduledExport) return;
  66.   assert(stage != E_ScheduledImport);
  67.   assert((int)stage == NIL);
  68.   p = (EnvironRecordPtr)malloc(sizeof(EnvironRecord));
  69.   p->id = id;
  70.   p->next = writeHead;
  71.   writeHead = p;
  72.   Map_Insert(environmentMap, (int)id, (int) E_ScheduledExport);
  73. }
  74.  
  75. /*
  76.  * This one runs through the list of things to write, and writes each of them
  77.  * in turn.  When writeTree writes a globalreference, it calls scheduleOutput
  78.  * to ensure that the object has been written out.
  79.  */
  80. void doOutput()
  81. {
  82.   EnvironRecordPtr p;
  83.   while (writeHead != NULL) {
  84.     p = writeHead;
  85.     writeHead = writeHead->next;
  86.     storeObject(p->id);
  87.     free((char *) p);
  88.   }
  89. }
  90.  
  91. Boolean environmentWasImported(id)
  92. OID id;
  93. {
  94.   EnvironmentStage stage;  
  95.   stage = (EnvironmentStage) Map_Lookup(environmentMap, (int)id);
  96.   if (stage == E_Imported) return(TRUE);
  97.   if (stage == E_ScheduledImport) assert(FALSE);
  98.   return(FALSE);
  99. }
  100.  
  101. void scheduleInput(id)
  102. OID id;
  103. {
  104.   EnvironmentStage stage;
  105.   EnvironRecordPtr p;
  106.  
  107.   stage = (EnvironmentStage) Map_Lookup(environmentMap, (int)id);
  108.   if (stage == E_Imported) return;
  109.   if (stage == E_ScheduledImport) return;
  110.   assert(stage != E_Exported);
  111.   assert(stage != E_ScheduledExport);
  112.   assert((int)stage == NIL);
  113.   p = (EnvironRecordPtr)malloc(sizeof(EnvironRecord));
  114.   p->id = id;
  115.   p->next = readHead;
  116.   readHead = p;
  117.   Map_Insert(environmentMap, (int)id, (int) E_ScheduledImport);
  118.   TRACE1(environment, 5, "Scheduling input of 0x%08x", id);
  119. }
  120.  
  121. void doInput()
  122. {
  123.   EnvironRecordPtr p;
  124.   while (readHead != NULL) {
  125.     p = readHead;
  126.     readHead = readHead->next;
  127.     (void) loadObject(p->id);
  128.     free((char *) p);
  129.   }
  130. }
  131.  
  132. static Map gMap;
  133. static Boolean doScheduleInput = FALSE;
  134.  
  135. static void r_scanForGlobals(p)
  136. register NodePtr p;
  137. {
  138.   register NodePtr q;
  139.   register Symbol st;
  140.   OID id;
  141.  
  142.   if ((int) p <= 0x200) return;
  143.   if (Map_Lookup(gMap, (int)p) != NIL) return;
  144.   Map_Insert(gMap, (int)p, 1);
  145.   switch (p->tag) {
  146.     case P_GLOBALREF:
  147.       assert(p->b.globalref.value == NULL);
  148.       if (doScheduleInput && Map_Lookup(objectTable, (int)p->b.globalref.id) == NIL) {
  149.     scheduleInput(p->b.globalref.id);
  150.       }
  151.       break;
  152.     case P_OBLIT:
  153.       id = p->b.atlit.id;
  154.       if (id != 0) {
  155.     OTInsert(p, id);
  156.     Map_Insert(environmentMap, (int)id, (int)E_Imported);
  157.       }
  158.       id = getCodeOID(p);
  159.       if (id != 0) {
  160.     OTInsert(p, id);
  161.     Map_Insert(environmentMap, (int)id, (int)E_Imported);
  162.       }
  163.       break;
  164.     case P_ATLIT:
  165.       id = p->b.atlit.id;
  166.       if (id != 0) {
  167.     OTInsert(p, id);
  168.     Map_Insert(environmentMap, (int)id, (int)E_Imported);
  169.       }
  170.       break;
  171.     case P_SYMDEF:
  172.     case P_SYMREF:
  173.       st = ST_Fetch(p->b.symdef.symbol);
  174.       if (st->value.ATinfo != NULL) r_scanForGlobals(st->value.ATinfo);
  175.       if (st->value.CTinfo != NULL) r_scanForGlobals(st->value.CTinfo);
  176.       if (st->value.value != NULL) r_scanForGlobals(st->value.value);
  177.       break;
  178.     default:
  179.       break;
  180.   }
  181.   Sequence_For(q, p)
  182.     if ((int) q >= 0x200) r_scanForGlobals(q);
  183.   Sequence_Next
  184. }
  185.  
  186. void scanForGlobals(p, dsi)
  187. NodePtr p;
  188. Boolean dsi;
  189. {
  190.   gMap = Map_Create();
  191.   doScheduleInput = dsi;
  192.   r_scanForGlobals(p);
  193.   Map_Destroy(gMap);
  194. }
  195.  
  196. NodePtr loadObject(id)
  197. OID id;
  198. {
  199.   char *theOIDFileName;
  200.   NodePtr s;
  201.   s = (NodePtr) Map_Lookup(objectTable, (int)id);
  202.   if ((int)s != NIL) {
  203.     TRACE1(environment, 5, "Already loaded 0x%08x", id);
  204.   } else {
  205.     Map_Insert(environmentMap, (int)id, (int)E_Imported);
  206.     theOIDFileName = makeOIDFileName(id);
  207.     TRACE1(environment, 5, "loading \"%s\"", theOIDFileName);
  208.     s = readTree(theOIDFileName);
  209.     free(theOIDFileName);
  210.     OTInsert(s, id);
  211.     /* Scan for global references. */
  212.     scanForGlobals(s, TRUE);
  213.   }
  214.   return(s);
  215. }
  216.  
  217. void storeObject(id)
  218. OID id;
  219. {
  220.   NodePtr p;
  221.   char *theOIDFileName, *theSecondOIDFileName;
  222.   p = (NodePtr) Map_Lookup(objectTable, (int)id);
  223.   assert((int)p != NIL);
  224.   assert(p->tag == P_OBLIT || p->tag == P_ATLIT);
  225.   if (p->tag == P_OBLIT && p->b.oblit.codeOID == id && p->b.oblit.id != 0) {
  226.     scheduleOutput(p->b.oblit.id);
  227.     if (bflag) {
  228.       Map_Insert(environmentMap, (int)id, (int)E_Exported);
  229.     } else {
  230.       Map_Insert(environmentMap, (int)id, (int)E_Exported);
  231.       theOIDFileName = makeOIDFileName(p->b.oblit.id);
  232.       theSecondOIDFileName = makeOIDFileName(p->b.oblit.codeOID);
  233.       myLink(theOIDFileName, theSecondOIDFileName, TRUE, p);
  234.       free(theOIDFileName);
  235.       free(theSecondOIDFileName);
  236.     }
  237.   } else if (p->b.oblit.id != id && p->b.oblit.codeOID != id) {
  238.     /* something weird, ignore it */
  239.     Map_Insert(environmentMap, (int)id, (int)E_Exported);
  240.   } else {
  241.     theOIDFileName = makeOIDFileName(id);
  242.     TRACE2(environment, 2, "storeObject: writing 0x%08x to \"%s\"", id,
  243.       theOIDFileName);
  244.     Map_Insert(environmentMap, (int)id, (int)E_Exported);
  245.     writeTree(theOIDFileName, p);
  246.     free(theOIDFileName);
  247.   }
  248. }
  249.  
  250. NodePtr OTLookup(id)
  251. OID id;
  252. {
  253.   register NodePtr q;
  254.  
  255.   q = (NodePtr) Map_Lookup(objectTable, (int) id);
  256.   if (q == (NodePtr) NIL) {
  257.     TRACE1(environment, 1, "Trying to find object 0x%08x", id);
  258.     scheduleInput(id);
  259.     doInput();
  260.   }
  261.   q = (NodePtr) Map_Lookup(objectTable, (int) id);
  262.   assert(q != (NodePtr) NIL);
  263.   return(q);
  264. }
  265.  
  266. void resolveGlobal(p, value)
  267. register NodePtr p;
  268. Value *value;
  269. {
  270.   NodePtr q;
  271.   assert(p->tag == P_GLOBALREF);
  272.   q = p->b.globalref.value;
  273.   if (q == NULL) {
  274.     q = OTLookup(p->b.globalref.id);
  275.     assert((int)q != NIL);
  276.     p->b.globalref.value = q;
  277.   }
  278.   /* q is now the value */
  279.   if (value != NULL) {
  280.     if (q->tag == P_OBLIT) {
  281.       value->value = q;
  282.       value->CTinfo = q;
  283.       assert(q->b.oblit.myat != NULL);
  284.       value->ATinfo = q->b.oblit.myat;
  285.     } else if (q->tag == P_ATLIT) {
  286.       value->value = q;
  287.       value->ATinfo = refToBuiltin(B_INSTAT, SIGNATUREINDEX);
  288.       value->CTinfo = refToBuiltin(B_INSTCT, SIGNATUREINDEX);
  289.     }
  290.   }
  291. }
  292.  
  293. void OTInsert(p, id)
  294. register NodePtr p;
  295. OID id;
  296. {
  297.   TRACE2(environment, 5, "OTInsert: OID 0x%08x as 0x%x.", id, p);
  298.   Map_Insert(objectTable, (int) id, (int)p);
  299. }
  300.  
  301. extern char *writeAT();
  302.  
  303. static char *ATInfo, thevaluespace[20];
  304. static datum keydatum, valuedatum;
  305.  
  306. Boolean isPossibleAnswer(id, thekeydatum)
  307. datum thekeydatum;
  308. OID id;
  309. {
  310.   char *treeFileName, *dotoFileName;
  311.   int sysresult;
  312.   struct stat statbuf;
  313.   Boolean theAnswer = TRUE;
  314.   if (Map_Lookup(objectTable, (int)id) != NIL) return(theAnswer);
  315.  
  316.   treeFileName = makeOIDFileName(id);
  317.   dotoFileName = makeOIDDotoFileName(id);
  318.   sysresult = stat(treeFileName, &statbuf);
  319.   if (sysresult < 0) {
  320.     if (errno == ENOENT) {
  321.       TRACE1(matchat, 1, "no tree file %s", treeFileName);
  322.       TRACE1(invoccache, 3, "no tree file %s", treeFileName);
  323.       theAnswer = FALSE;
  324.     } else {
  325.       fprintf(stdout, "Cannot stat %s: %s", treeFileName,
  326.     errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  327.       exit(1);
  328.     }
  329.   }
  330.   if (!bflag && theAnswer) {
  331.     sysresult = stat(dotoFileName, &statbuf);
  332.     if (sysresult < 0) {
  333.       if (errno == ENOENT) {
  334.     TRACE1(matchat, 1, "no doto file %s", dotoFileName);
  335.     TRACE1(invoccache, 3, "no doto file %s", dotoFileName);
  336.     theAnswer = FALSE;
  337.       } else {
  338.     fprintf(stdout, "Cannot stat %s: %s", dotoFileName,
  339.       errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
  340.     exit(1);
  341.       }
  342.     }
  343.   }
  344.   free(dotoFileName);
  345.   free(treeFileName);
  346.   if (!theAnswer) {
  347.     dbm_delete(emDBM, thekeydatum);
  348.   }
  349.   return(theAnswer);
  350. }
  351.  
  352. OID isDuplicateAT(p)
  353. register NodePtr p;
  354. {
  355.   OID resultOID;
  356.   NodePtr anob;
  357.   if (p->tag != P_ATLIT ||
  358.       p->b.atlit.name == NULL ||
  359.       p->b.atlit.f.isTypeVariable ||
  360.       p->b.atlit.f.dependsOnTypeVariable) return(0);
  361.   ATInfo = writeAT(p, FALSE, FALSE);
  362.   if (ATInfo == NULL) {
  363.     TRACE0(matchat, 1, "Cannot write (not figure out yet) AT");
  364.     keydatum.dptr = NULL;
  365.     keydatum.dsize = 0;
  366.     return(0);
  367.   }
  368.   IFTRACE(matchat, 1) {
  369.     printf("%s: %s", ST_SymbolName(p->b.atlit.name->b.symdef.symbol), ATInfo);
  370.   }
  371.   TRACE1(matchat, 1, "EI: The key is %s", ATInfo);
  372.   keydatum.dptr = ATInfo;
  373.   keydatum.dsize = strlen(ATInfo);
  374.   valuedatum = dbm_fetch(emDBM, keydatum);
  375.   TRACE2(matchat, 1, "The result of fetch = \"%.*s\"", valuedatum.dsize,
  376.     valuedatum.dptr);
  377.   if (valuedatum.dptr != NULL) {
  378.     bcopy(valuedatum.dptr, thevaluespace, valuedatum.dsize);
  379.     *(thevaluespace+valuedatum.dsize) = '\0';
  380.     if (sscanf(thevaluespace, "O0x%x", &resultOID) != 1) assert(FALSE);
  381.     TRACE1(matchat, 1, "Found it, result OID 0x%08x", resultOID);
  382.     TRACE0(matchat, 1, "Checking the possiblity of the result");
  383.     if (! isPossibleAnswer(resultOID, keydatum)) {
  384.       TRACE0(matchat, 1, "That is not a possible answer.");
  385.     } else {
  386.       anob = OTLookup(resultOID);
  387.       TRACE2(matchat, 1, "Result object = 0x%08x %s", anob, ATName(anob));
  388.       free(ATInfo);
  389.       return(resultOID);
  390.     }
  391.   }
  392.   TRACE0(matchat, 1, "Did not find it.");
  393.   resultOID = 0;
  394.   return(resultOID);
  395. }
  396.  
  397. extern void ensureGenerate();
  398.  
  399. void defineAT(p)
  400. NodePtr p;
  401. {
  402.   int storeResult;
  403.   if (p->tag != P_ATLIT ||
  404.       p->b.atlit.name == NULL ||
  405.       p->b.atlit.f.isTypeVariable ||
  406.       p->b.atlit.f.dependsOnTypeVariable) return;
  407.   if (keydatum.dptr == NULL) return;
  408.   sprintf(thevaluespace, "O0x%08x", p->b.atlit.id);
  409.   valuedatum.dptr = thevaluespace;
  410.   valuedatum.dsize = strlen(thevaluespace);
  411.   TRACE2(matchat, 1, "storing %s with key %s", ATName(p),
  412.     keydatum.dptr);
  413.   if ((storeResult = dbm_store(emDBM, keydatum, valuedatum, DBM_REPLACE)) < 0) assert(FALSE);
  414.   free(keydatum.dptr);
  415.   keydatum.dptr = writeAT(p, TRUE, FALSE);
  416.   if (keydatum.dptr == NULL) {
  417.     TRACE0(matchat, 1, "Cannot write (not figured out yet) AT");
  418.     return;
  419.   }
  420.   keydatum.dsize = strlen(keydatum.dptr);
  421.   storeResult = dbm_store(emDBM, keydatum, valuedatum, DBM_REPLACE);
  422.   if (storeResult < 0) assert(FALSE);
  423.   free(keydatum.dptr);  
  424.   scheduleOutput(p->b.atlit.id);
  425.   ensureGenerate(p->b.atlit.id);
  426. }
  427.  
  428. void defineGlobal(p, id)
  429. register NodePtr p;
  430. OID id;
  431. {
  432.   OID newID = 0;
  433.   p->b.oblit.f.isManifest = TRUE;
  434.   p->b.oblit.f.writeSeparately = TRUE;
  435.   if (!bflag && p->tag == P_ATLIT) {
  436.     newID = isDuplicateAT(p);
  437.     if (newID != 0) {
  438.       p->b.atlit.id = newID;
  439.       return;
  440.     }
  441.   }
  442.   if (id == 0) {
  443.     newID = AllocateOID();
  444.     if (p->tag == P_OBLIT && ! p->b.oblit.f.immutable) {
  445.       assert(Zflag);
  446.       newID &= 0xfeffffff;
  447.     }
  448.   } else {
  449.     newID = id;
  450.   }
  451.   p->b.oblit.id = newID;
  452.   if (p->b.oblit.f.isTypeVariable) {
  453.     fprintf(stderr, "Type Variable 0x%.8x (OID 0x%08x) set writeSeparately\n",
  454.       p, p->b.oblit.id);
  455.   }
  456.   OTInsert(p, p->b.oblit.id);
  457.   if (!bflag && p->tag == P_ATLIT) {
  458.     defineAT(p);
  459.   }
  460. }
  461.  
  462. void setStage(id, stage)
  463. OID id;
  464. EnvironmentStage stage;
  465. {
  466.   Map_Insert(environmentMap, (int)id, stage);
  467. }
  468.  
  469. extern char *builtinNames[];
  470.  
  471. static OID lookup(fPathName, fName)
  472. char *fPathName, *fName;
  473. {
  474.   FILE *fp;
  475.   char buffer[256], entry[256], *status, *filename;
  476.   OID oid;
  477.   Boolean found = FALSE;
  478.   int i;
  479.  
  480.   if (! bflag && (!strcmp(fPathName, "Builtins") || !strcmp(fPathName, "builtins"))) {
  481.     (void) sprintf(entry, "_%sobject", fName);
  482.     for (i = 0; builtinNames[i] && strcmp(builtinNames[i], entry); i++) ;
  483.     if (builtinNames[i] != NULL) {
  484.       found = TRUE;
  485.       oid = OIDOfBuiltin(B_IT, i);
  486.     }
  487.   } else {
  488.     filename = malloc((unsigned)(strlen(emdbDirectory)+strlen(fPathName)+30));
  489.     (void) sprintf(filename, "%s/Trees/Map/%s", emdbDirectory, fPathName);
  490.     fp = fopen(filename, "r+");
  491.     if (fp == NULL) return(0);
  492.     free(filename);
  493.     status = fgets(buffer, 256, fp);
  494.     while (status != NULL) {
  495.       if (sscanf(buffer, "%[^ ] 0x%x", entry, &oid) != 2) assert(FALSE);
  496.       if (! strcmp (entry, fName)) {
  497.     found = TRUE;
  498.     break;
  499.       }
  500.       status = fgets(buffer, 256, fp);
  501.     }
  502.     if (fclose(fp) == EOF) assert(FALSE);
  503.   }
  504.   return(found ? oid : 0);
  505. }
  506.   
  507. static Boolean install(fPathName, fName, fOID)
  508. char *fPathName, *fName;
  509. OID fOID;
  510. {
  511.   FILE *fp;
  512.   char buffer[256], entry[256], *status, *filename;
  513.   OID oid;
  514.   int where;
  515.   Boolean found = FALSE;
  516.  
  517.   filename = malloc((unsigned)(strlen(emdbDirectory)+strlen(fPathName)+30));
  518.   (void) sprintf(filename, "%s/Trees/Map/%s", emdbDirectory, fPathName);
  519.   fp = fopen(filename, "r+");
  520.   if (fp == NULL) {
  521.     if (errno == ENOENT) {
  522.       fp = fopen(filename, "w+");
  523.       if (fp == NULL) return(FALSE);
  524.     } else {
  525.       return(FALSE);
  526.     }
  527.   } 
  528.   free(filename);
  529.   where = ftell(fp);
  530.   status = fgets(buffer, 256, fp);
  531.   while (status != NULL) {
  532.     if (sscanf(buffer, "%[^ ] 0x%x", entry, &oid) != 2) assert(FALSE);
  533.     if (! strcmp (entry, fName)) {
  534.       if (fseek(fp, (long)where, 0) == -1) assert(FALSE);
  535.       fprintf(fp, "%s 0x%08x\n", fName, fOID);
  536.       found = TRUE;
  537.       break;
  538.     }
  539.     where = ftell(fp);
  540.     status = fgets(buffer, 256, fp);
  541.   }
  542.   if (! found) {
  543.     if (fseek(fp, 0L, 2) == -1) assert(FALSE);
  544.     fprintf(fp, "%s 0x%08x\n", fName, fOID);
  545.   }
  546.   if (fclose(fp) == EOF) assert(FALSE);
  547.   return(TRUE);
  548. }
  549.  
  550. char *makeOIDFileName(fOID)
  551. OID fOID;
  552. {
  553.   char *filename;
  554.   if (bflag) {
  555.     /* cheat and put them here. */
  556.     filename = (char *) malloc(100);
  557.     (void) sprintf(filename, "OID%08x.t", fOID);
  558.   } else {
  559.     filename = (char *) malloc((unsigned) strlen(emdbDirectory) + 40);
  560.     (void) sprintf(filename, "%s/Trees/Objects_%0.1x/OID%08x.t", 
  561.       emdbDirectory, fOID & 0xf, fOID);
  562.   }
  563.   return(filename);
  564. }
  565.  
  566. char *makeOIDDotoFileName(fOID)
  567. OID fOID;
  568. {
  569.   char *filename;
  570.   filename = (char *) malloc((unsigned) strlen(emdbDirectory) + 40);
  571.   (void) sprintf(filename, "%s/Dotos/Objects_%0.1x/OID%08x.o", 
  572.     emdbDirectory, fOID & 0xf, fOID);
  573.   return(filename);
  574. }
  575.  
  576. void doImports(p)
  577. register NodePtr p;
  578. {
  579.   Symbol sym;
  580.   register NodePtr q, symbolList, r, s;
  581.   char *pathName, *objectName;
  582.   OID theOID;
  583.  
  584.   assert(p->tag == P_COMP);
  585.   p = p->b.comp.import;
  586.   if (p == NULL) return;
  587.   assert(p->tag == T_SEQUENCE);
  588.   Sequence_For(q, p)
  589.     assert(q->tag == P_IMPORT);
  590.     symbolList = q->b.import.syms;
  591.     assert(q->b.import.path->tag == T_STRING);
  592.     pathName = q->b.import.path->b.string.string;
  593.     Sequence_For(r, symbolList)
  594.       sym = ST_Fetch(r->b.symref.symbol);
  595.       objectName = Ident_Name(sym->itsIdent);
  596.       TRACE2(passes, 1, "Looking up %s in %s.", objectName, pathName);
  597.       theOID = lookup(pathName, objectName);
  598.       if (theOID == 0) {
  599.     ErrorMessage(r, "Name \"%s\" undefined in \"%s\"",
  600.       objectName, pathName);
  601.       } else {
  602.     if (bflag && loadedDummyBuiltins) {
  603.       Map_Delete(objectTable, (int)theOID);
  604.       Map_Delete(environmentMap, (int)theOID);
  605.     }
  606.     s = OTLookup(theOID);
  607.     sym->value.value = s;
  608.     sym->isManifest = TRUE;
  609.     sym->hasValue = TRUE;
  610.     if (s->tag == P_OBLIT) {
  611.       sym->value.CTinfo = s;
  612.       if (! bflag) {
  613.         assert(s->b.oblit.myat != NULL);
  614.         sym->value.ATinfo = s->b.oblit.myat;
  615.       } else {
  616.         sym->value.ATinfo = refToBuiltin(B_INSTAT, ANYINDEX);
  617.       }
  618.     } else if (s->tag == P_ATLIT) {
  619.       sym->value.ATinfo = refToBuiltin(B_INSTAT, SIGNATUREINDEX);
  620.       sym->value.CTinfo = refToBuiltin(B_INSTCT, SIGNATUREINDEX);
  621.     }
  622.       }
  623.     Sequence_Next
  624.   Sequence_Next
  625.   doInput();
  626. }
  627.  
  628. void doExports(p)
  629. register NodePtr p;
  630. {
  631.   Symbol sym;
  632.   register NodePtr q, symbolList, r, s;
  633.   char *pathName, *objectName;
  634.   OID theOID;
  635.  
  636.   assert(p->tag == P_COMP);
  637.   p = p->b.comp.export;
  638.   assert(isASequence(p));
  639.   Sequence_For(q, p)
  640.     assert(q->tag == P_EXPORT);
  641.     symbolList = q->b.export.syms;
  642.     assert(q->b.export.path->tag == T_STRING);
  643.     pathName = q->b.export.path->b.string.string;
  644.     Sequence_For(r, symbolList)
  645.       sym = ST_Fetch(r->b.symref.symbol);
  646.       objectName = Ident_Name(sym->itsIdent);
  647.       s = GETVALUE(sym->value.value);
  648.       if (s == NULL) {
  649.     ErrorMessage(r, "Exported symbol \"%s\" is not manifest",
  650.       ST_SymbolName(sym));
  651.       } else if (s->tag != P_ATLIT && s->tag != P_OBLIT) {
  652.     ErrorMessage(r, "Implementation restriction:\n\
  653. \tonly object literals and type literals can be exported");
  654.       } else {
  655.     assert(s->b.atlit.f.isManifest || s->b.atlit.f.dependsOnTypeVariable);
  656.     if (bflag) {
  657.       prepareBuiltinForOutput(s, objectName);
  658.     } else {
  659.       if (s->b.atlit.id == 0) {
  660.         s->b.atlit.id = AllocateOID();
  661.         OTInsert(s, s->b.atlit.id);
  662.       }
  663.     }
  664.     theOID = s->b.atlit.id;
  665.     TRACE3(passes, 1, "Installing %s (oid 0x%08x) in %s.",
  666.       objectName, theOID, pathName);
  667.     if (! install(pathName, objectName, theOID)) {
  668.       ErrorMessage(r, "Could not install \"%s\" in \"%s\"",
  669.         objectName, pathName);
  670.     } else {
  671.       storeObject(theOID);
  672.     }
  673.       }
  674.     Sequence_Next
  675.   Sequence_Next
  676.   doOutput();
  677.   if (bflag) {
  678.     Map_Destroy(translateOIDMap);
  679.     translateOIDMap = NULL;
  680.   }
  681. }
  682.  
  683. ensureDirectory(name)
  684. char *name;
  685. {
  686.   struct stat buf;
  687.   int res;
  688.   if ((res = stat(name, &buf)) < 0) {
  689.     if (mkdir(name, 0777) < 0) {
  690.       fprintf(stderr, "Can't create directory %s\n", name);
  691.       numberOfSemanticErrors++;
  692.     }
  693.     res = stat(name, &buf);
  694.   }
  695.   if (res < 0) {
  696.     fprintf(stderr, "Couldn't stat directory %s\n", name);
  697.     perror("mkdir");
  698.   } else {
  699.     if (! (buf.st_mode & S_IFDIR)) {
  700.       fprintf(stderr, "%s should be, but is not, a directory\n", name);
  701.     }
  702.   }
  703. }
  704.  
  705. initializeDataBaseFiles()
  706. {
  707.   char pname[1024], *s;
  708.   struct stat buf;
  709.   ensureDirectory(emdbDirectory);
  710.   sprintf(pname, "%s/initialized", emdbDirectory);
  711.   if (stat(pname, &buf) >= 0) return;
  712.   sprintf(pname, "%s/DB", emdbDirectory);
  713.   ensureDirectory(pname);
  714.   sprintf(pname, "%s/Trees", emdbDirectory);
  715.   ensureDirectory(pname);
  716.   sprintf(pname, "%s/Trees/Map", emdbDirectory);
  717.   ensureDirectory(pname);
  718.   sprintf(pname, "%s/Dotos", emdbDirectory);
  719.   ensureDirectory(pname);
  720.   for (s = "0123456789abcdef"; *s; s++) {
  721.     sprintf(pname, "%s/Trees/Objects_%c", emdbDirectory, *s);
  722.     ensureDirectory(pname);
  723.     sprintf(pname, "%s/Dotos/Objects_%c", emdbDirectory, *s);
  724.     ensureDirectory(pname);
  725.   }
  726.   sprintf(pname, "%s/initialized", emdbDirectory);
  727.   close(open(pname, O_RDWR | O_CREAT, 0777));
  728. }
  729.